// GLib.Value.cs - GLib Value class implementation
//
// Author: Mike Kestner <mkestner@speakeasy.net>
//
// Copyright (c) 2001 Mike Kestner
// Copyright (c) 2003-2004 Novell, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the Lesser GNU General 
// Public License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.


namespace GLib {

	using System;
	using System.Reflection;
	using System.Runtime.InteropServices;

	[StructLayout(LayoutKind.Sequential)]
	public struct Value : IDisposable {

		IntPtr type;
#pragma warning disable 0414
		long pad1;
		long pad2;
#pragma warning restore 0414

		public static Value Empty;

		public Value(GLib.GType gtype) {
			type = IntPtr.Zero;
			pad1 = pad2 = 0;
			g_value_init(ref this, gtype.Val);
		}

		public Value(object obj) {
			type = IntPtr.Zero;
			pad1 = pad2 = 0;

			GType gtype = (GType)obj.GetType();
			g_value_init(ref this, gtype.Val);
			Val = obj;
		}

		public Value(bool val) : this(GType.Boolean) {
			g_value_set_boolean(ref this, val);
		}

		public Value(byte val) : this(GType.UChar) {
			g_value_set_uchar(ref this, val);
		}

		public Value(sbyte val) : this(GType.Char) {
			g_value_set_char(ref this, val);
		}

		public Value(int val) : this(GType.Int) {
			g_value_set_int(ref this, val);
		}

		public Value(uint val) : this(GType.UInt) {
			g_value_set_uint(ref this, val);
		}

		public Value(ushort val) : this(GType.UInt) {
			g_value_set_uint(ref this, val);
		}

		public Value(long val) : this(GType.Int64) {
			g_value_set_int64(ref this, val);
		}

		public Value(ulong val) : this(GType.UInt64) {
			g_value_set_uint64(ref this, val);
		}

		public Value(float val) : this(GType.Float) {
			g_value_set_float(ref this, val);
		}

		public Value(double val) : this(GType.Double) {
			g_value_set_double(ref this, val);
		}

		public Value(string val) : this(GType.String) {
			IntPtr native_val = GLib.Marshaller.StringToPtrGStrdup(val);
			g_value_set_string(ref this, native_val);
			GLib.Marshaller.Free(native_val);
		}

		public Value(ValueArray val) : this(ValueArray.GType) {
			g_value_set_boxed(ref this, val.Handle);
		}

		public Value(IntPtr val) : this(GType.Pointer) {
			g_value_set_pointer(ref this, val);
		}

		public Value(Variant variant) : this(GType.Variant) {
			g_value_set_variant(ref this, variant == null ? IntPtr.Zero : variant.Handle);
		}

		public Value(Opaque val, string type_name) {
			type = IntPtr.Zero;
			pad1 = pad2 = 0;
			g_value_init(ref this, GType.FromName(type_name).Val);
			g_value_set_boxed(ref this, val.Handle);
		}

		public Value(GLib.Object val) : this(val == null ? GType.Object : val.NativeType) {
			g_value_set_object(ref this, val == null ? IntPtr.Zero : val.Handle);
		}

		public Value(GLib.GInterfaceAdapter val) : this(val == null ? GType.Object : val.GInterfaceGType) {
			g_value_set_object(ref this, val == null ? IntPtr.Zero : val.Handle);
		}

		public Value(GLib.Object obj, string prop_name) {
			type = IntPtr.Zero;
			pad1 = pad2 = 0;
			InitForProperty(obj, prop_name);
		}

		[Obsolete]
		public Value(IntPtr obj, string prop_name, Opaque val) {
			type = IntPtr.Zero;
			pad1 = pad2 = 0;
			InitForProperty(GLib.Object.GetObject(obj), prop_name);
			g_value_set_boxed(ref this, val.Handle);
		}

		public Value(string[] val) : this(new GLib.GType(g_strv_get_type())) {
			if (val == null) {
				g_value_set_boxed(ref this, IntPtr.Zero);
				return;
			}

			IntPtr native_array = Marshal.AllocHGlobal((val.Length + 1) * IntPtr.Size);
			for (int i = 0; i < val.Length; i++)
				Marshal.WriteIntPtr(native_array, i * IntPtr.Size, GLib.Marshaller.StringToPtrGStrdup(val[i]));
			Marshal.WriteIntPtr(native_array, val.Length * IntPtr.Size, IntPtr.Zero);

			g_value_set_boxed(ref this, native_array);

			for (int i = 0; i < val.Length; i++)
				GLib.Marshaller.Free(Marshal.ReadIntPtr(native_array, i * IntPtr.Size));
			Marshal.FreeHGlobal(native_array);
		}

		public void Dispose() {
			g_value_unset(ref this);
		}

		public void Init(GLib.GType gtype) {
			g_value_init(ref this, gtype.Val);
		}


		public static explicit operator bool(Value val) {
			return g_value_get_boolean(ref val);
		}

		public static explicit operator byte(Value val) {
			return g_value_get_uchar(ref val);
		}

		public static explicit operator sbyte(Value val) {
			return g_value_get_char(ref val);
		}

		public static explicit operator int(Value val) {
			return g_value_get_int(ref val);
		}

		public static explicit operator uint(Value val) {
			return g_value_get_uint(ref val);
		}

		public static explicit operator ushort(Value val) {
			return (ushort)g_value_get_uint(ref val);
		}

		public static explicit operator long(Value val) {
			if (val.type == GType.Long.Val)
				return val.GetLongForPlatform();
			else
				return g_value_get_int64(ref val);
		}

		public static explicit operator ulong(Value val) {
			if (val.type == GType.ULong.Val)
				return val.GetULongForPlatform();
			else
				return g_value_get_uint64(ref val);
		}

		public static explicit operator Enum(Value val) {
			if (val.HoldsFlags)
				return (Enum)Enum.ToObject(GType.LookupType(val.type), g_value_get_flags(ref val));
			else
				return (Enum)Enum.ToObject(GType.LookupType(val.type), g_value_get_enum(ref val));
		}

		public static explicit operator float(Value val) {
			return g_value_get_float(ref val);
		}

		public static explicit operator double(Value val) {
			return g_value_get_double(ref val);
		}

		public static explicit operator GLib.GType(Value val) {
			return g_value_get_gtype(ref val);
		}


		public static explicit operator string(Value val) {
			IntPtr str = g_value_get_string(ref val);
			return str == IntPtr.Zero ? null : GLib.Marshaller.Utf8PtrToString(str);
		}

		public static explicit operator ValueArray(Value val) {
			return new ValueArray(g_value_get_boxed(ref val));
		}

		public static explicit operator IntPtr(Value val) {
			return g_value_get_pointer(ref val);
		}

		public static explicit operator GLib.Opaque(Value val) {
			return GLib.Opaque.GetOpaque(g_value_get_boxed(ref val), (Type)new GType(val.type), false);
		}

		public static explicit operator GLib.Variant(Value Val) {
			return new Variant(g_value_get_variant(ref Val));
		}

		public static explicit operator GLib.VariantType(Value val) {
			return new VariantType(g_value_get_boxed(ref val));
		}

		public static explicit operator GLib.Object(Value val) {
			return GLib.Object.GetObject(g_value_get_object(ref val), false);
		}

		public static explicit operator string[](Value val) {
			IntPtr native_array = g_value_get_boxed(ref val);
			if (native_array == IntPtr.Zero)
				return null;

			int count = 0;
			while (Marshal.ReadIntPtr(native_array, count * IntPtr.Size) != IntPtr.Zero)
				count++;
			string[] strings = new string[count];
			for (int i = 0; i < count; i++)
				strings[i] = GLib.Marshaller.Utf8PtrToString(Marshal.ReadIntPtr(native_array, i * IntPtr.Size));
			return strings;
		}

		object ToRegisteredType() {
			Type t = GLib.GType.LookupType(type);
			ConstructorInfo ci = null;

			try {
				while (ci == null && t != null) {
					if (!t.IsAbstract)
						ci = t.GetConstructor(new Type[] { typeof(GLib.Value) });
					if (ci == null)
						t = t.BaseType;
				}
			} catch (Exception) {
				ci = null;
			}

			if (ci == null)
				throw new Exception("Unknown type " + new GType(type).ToString());

			return ci.Invoke(new object[] { this });
		}

		void FromRegisteredType(object val) {
			Type t = GLib.GType.LookupType(type);
			MethodInfo mi = null;

			try {
				while (mi == null && t != null) {
					mi = t.GetMethod("SetGValue", new Type[] { Type.GetType("GLib.Value&") });
					if (mi != null && (mi.IsAbstract || mi.ReturnType != typeof(void)))
						mi = null;
					if (mi == null)
						t = t.BaseType;
				}
			} catch (Exception) {
				mi = null;
			}

			if (mi == null)
				throw new Exception("Unknown type " + new GType(type).ToString());

			object[] parameters = new object[] { this };
			mi.Invoke(val, parameters);
			this = (GLib.Value)parameters[0];
		}

		long GetLongForPlatform() {
			switch (Environment.OSVersion.Platform) {
				case PlatformID.Win32NT:
				case PlatformID.Win32S:
				case PlatformID.Win32Windows:
				case PlatformID.WinCE:
					return (long)g_value_get_long_as_int(ref this);
				default:
					return g_value_get_long(ref this).ToInt64();
			}
		}

		ulong GetULongForPlatform() {
			switch (Environment.OSVersion.Platform) {
				case PlatformID.Win32NT:
				case PlatformID.Win32S:
				case PlatformID.Win32Windows:
				case PlatformID.WinCE:
					return (ulong)g_value_get_ulong_as_uint(ref this);
				default:
					return g_value_get_ulong(ref this).ToUInt64();
			}
		}

		void SetLongForPlatform(long val) {
			switch (Environment.OSVersion.Platform) {
				case PlatformID.Win32NT:
				case PlatformID.Win32S:
				case PlatformID.Win32Windows:
				case PlatformID.WinCE:
					g_value_set_long(ref this, (int)val);
					break;
				default:
					g_value_set_long(ref this, new IntPtr(val));
					break;
			}
		}

		void SetULongForPlatform(ulong val) {
			switch (Environment.OSVersion.Platform) {
				case PlatformID.Win32NT:
				case PlatformID.Win32S:
				case PlatformID.Win32Windows:
				case PlatformID.WinCE:
					g_value_set_ulong(ref this, (uint)val);
					break;
				default:
					g_value_set_ulong(ref this, new UIntPtr(val));
					break;
			}
		}

		object ToEnum() {
			Type t = GType.LookupType(type);

			if (t == null) {
				if (HoldsFlags)
					return g_value_get_flags(ref this);
				else
					return g_value_get_enum(ref this);
			} else {
				return (Enum)this;
			}
		}

		object ToBoxed() {
			IntPtr boxed_ptr = g_value_get_boxed(ref this);

			if (boxed_ptr == IntPtr.Zero)
				return null;

			Type t = GType.LookupType(type);
			if (t == null)
				throw new Exception("Unknown type " + new GType(type).ToString());
			else if (t.IsSubclassOf(typeof(GLib.Opaque)))
				return (GLib.Opaque)this;

			MethodInfo mi = t.GetMethod("New", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy, null, new Type[] { typeof(IntPtr) }, null);
			if (mi != null)
				return mi.Invoke(null, new object[] { boxed_ptr });

			ConstructorInfo ci = t.GetConstructor(new Type[] { typeof(IntPtr), typeof(bool) });
			if (ci != null)
				return ci.Invoke(new object[] { boxed_ptr, false });

			ci = t.GetConstructor(new Type[] { typeof(IntPtr) });
			if (ci != null)
				return ci.Invoke(new object[] { boxed_ptr });

			return Marshal.PtrToStructure(boxed_ptr, t);
		}

		public object Val {
			get {
				if (type == GType.Boolean.Val)
					return (bool)this;
				else if (type == GType.UChar.Val)
					return (byte)this;
				else if (type == GType.Char.Val)
					return (sbyte)this;
				else if (type == GType.Int.Val)
					return (int)this;
				else if (type == GType.UInt.Val)
					return (uint)this;
				else if (type == GType.Int64.Val)
					return (long)this;
				else if (type == GType.Long.Val)
					return GetLongForPlatform();
				else if (type == GType.UInt64.Val)
					return (ulong)this;
				else if (type == GType.ULong.Val)
					return GetULongForPlatform();
				else if (GType.Is(type, GType.Enum) ||
					 GType.Is(type, GType.Flags))
					return ToEnum();
				else if (type == GType.Float.Val)
					return (float)this;
				else if (type == GType.Double.Val)
					return (double)this;
				else if (type == GType.String.Val)
					return (string)this;
				else if (type == GType.Pointer.Val)
					return (IntPtr)this;
				else if (type == GType.Variant.Val)
					return (GLib.Variant)this;
				else if (type == GType.Param.Val)
					return g_value_get_param(ref this);
				else if (type == ValueArray.GType.Val)
					return new ValueArray(g_value_get_boxed(ref this));
				else if (type == ManagedValue.GType.Val)
					return ManagedValue.ObjectForWrapper(g_value_get_boxed(ref this));
				else if (GType.Is(type, GType.Object))
					return (GLib.Object)this;
				else if (GType.Is(type, GType.Boxed))
					return ToBoxed();
				else if (GType.LookupType(type) != null)
					return ToRegisteredType();
				else if (type == IntPtr.Zero)
					return null;
				else
					throw new Exception("Unknown type " + new GType(type).ToString());
			}
			set {
				if (type == GType.Boolean.Val)
					g_value_set_boolean(ref this, (bool)value);
				else if (type == GType.UChar.Val)
					g_value_set_uchar(ref this, (byte)value);
				else if (type == GType.Char.Val)
					g_value_set_char(ref this, (sbyte)value);
				else if (type == GType.Int.Val)
					g_value_set_int(ref this, (int)value);
				else if (type == GType.UInt.Val)
					g_value_set_uint(ref this, (uint)value);
				else if (type == GType.Int64.Val)
					g_value_set_int64(ref this, (long)value);
				else if (type == GType.Long.Val)
					SetLongForPlatform((long)value);
				else if (type == GType.UInt64.Val)
					g_value_set_uint64(ref this, (ulong)value);
				else if (type == GType.ULong.Val)
					SetULongForPlatform(Convert.ToUInt64(value));
				else if (GType.Is(type, GType.Enum))
					g_value_set_enum(ref this, (int)value);
				else if (GType.Is(type, GType.Flags))
					g_value_set_flags(ref this, (uint)(int)value);
				else if (type == GType.Float.Val)
					g_value_set_float(ref this, (float)value);
				else if (type == GType.Double.Val)
					g_value_set_double(ref this, (double)value);
				else if (type == GType.Variant.Val)
					g_value_set_variant(ref this, ((GLib.Variant)value).Handle);
				else if (type == GType.String.Val) {
					IntPtr native = GLib.Marshaller.StringToPtrGStrdup((string)value);
					g_value_set_string(ref this, native);
					GLib.Marshaller.Free(native);
				} else if (type == GType.Pointer.Val) {
					if (value.GetType() == typeof(IntPtr)) {
						g_value_set_pointer(ref this, (IntPtr)value);
						return;
					} else if (value is IWrapper) {
						g_value_set_pointer(ref this, ((IWrapper)value).Handle);
						return;
					}
					IntPtr buf = Marshal.AllocHGlobal(Marshal.SizeOf(value.GetType()));
					Marshal.StructureToPtr(value, buf, false);
					g_value_set_pointer(ref this, buf);
				} else if (type == GType.Param.Val) {
					g_value_set_param(ref this, (IntPtr)value);
				} else if (type == ValueArray.GType.Val) {
					g_value_set_boxed(ref this, ((ValueArray)value).Handle);
				} else if (type == ManagedValue.GType.Val) {
					IntPtr wrapper = ManagedValue.WrapObject(value);
					g_value_set_boxed(ref this, wrapper);
					ManagedValue.ReleaseWrapper(wrapper);
				} else if (GType.Is(type, GType.Object))
					if (value is GLib.Object)
						g_value_set_object(ref this, (value as GLib.Object).Handle);
					else
						g_value_set_object(ref this, ((GInterfaceAdapter)value).Handle);
				else if (GType.Is(type, GType.Boxed)) {
					if (value is IWrapper) {
						g_value_set_boxed(ref this, ((IWrapper)value).Handle);
						return;
					}
					IntPtr buf = Marshaller.StructureToPtrAlloc(value);
					g_value_set_boxed(ref this, buf);
					Marshal.FreeHGlobal(buf);
				} else if (GLib.GType.LookupType(type) != null) {
					FromRegisteredType(value);
				} else
					throw new Exception("Unknown type " + new GType(type).ToString());
			}
		}

		internal void Update(object val) {
			if (GType.Is(type, GType.Boxed) && val != null && !(val is IWrapper)) {
				MethodInfo mi = val.GetType().GetMethod("Update", BindingFlags.NonPublic | BindingFlags.Instance);
				IntPtr boxed_ptr = g_value_get_boxed(ref this);

				if (mi == null && !val.GetType().IsDefined(typeof(StructLayoutAttribute), false))
					return;

				if (mi == null)
					Marshal.StructureToPtr(val, boxed_ptr, false);
				else
					mi.Invoke(val, null);
			}
		}

		bool HoldsFlags {
			get { return g_type_check_value_holds(ref this, GType.Flags.Val); }
		}

		void InitForProperty(Object obj, string name) {
			GType gtype = obj.NativeType;
			InitForProperty(gtype, name);
		}

		void InitForProperty(GType gtype, string name) {
			IntPtr p_name = Marshaller.StringToPtrGStrdup(name);
			IntPtr spec_ptr = g_object_class_find_property(gtype.GetClassPtr(), p_name);
			Marshaller.Free(p_name);

			if (spec_ptr == IntPtr.Zero)
				throw new Exception(String.Format("No property with name '{0}' in type '{1}'", name, gtype.ToString()));

			ParamSpec spec = new ParamSpec(spec_ptr);
			g_value_init(ref this, spec.ValueType.Val);
		}

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr g_object_class_find_property(IntPtr klass, IntPtr name);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern bool g_type_check_value_holds(ref Value val, IntPtr gtype);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_init(ref GLib.Value val, IntPtr gtype);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_unset(ref GLib.Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_boolean(ref Value val, bool data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_uchar(ref Value val, byte data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_char(ref Value val, sbyte data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_boxed(ref Value val, IntPtr data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_double(ref Value val, double data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_float(ref Value val, float data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_int(ref Value val, int data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_int64(ref Value val, long data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_long(ref Value val, IntPtr data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_long(ref Value val, int data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_uint64(ref Value val, ulong data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_object(ref Value val, IntPtr data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_param(ref Value val, IntPtr data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_pointer(ref Value val, IntPtr data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_string(ref Value val, IntPtr data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_uint(ref Value val, uint data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_ulong(ref Value val, UIntPtr data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_ulong(ref Value val, uint data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_enum(ref Value val, int data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_flags(ref Value val, uint data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern void g_value_set_variant(ref Value val, IntPtr data);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern bool g_value_get_boolean(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern byte g_value_get_uchar(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern sbyte g_value_get_char(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr g_value_get_boxed(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern double g_value_get_double(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern float g_value_get_float(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern GLib.GType g_value_get_gtype(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern int g_value_get_int(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern long g_value_get_int64(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr g_value_get_long(ref Value val);

		[DllImport(Global.GObjectNativeDll, EntryPoint = "g_value_get_long", CallingConvention = CallingConvention.Cdecl)]
		static extern int g_value_get_long_as_int(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern ulong g_value_get_uint64(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern UIntPtr g_value_get_ulong(ref Value val);

		[DllImport(Global.GObjectNativeDll, EntryPoint = "g_value_get_ulong", CallingConvention = CallingConvention.Cdecl)]
		static extern int g_value_get_ulong_as_uint(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr g_value_get_object(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr g_value_get_param(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr g_value_get_pointer(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr g_value_get_string(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern uint g_value_get_uint(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern int g_value_get_enum(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern uint g_value_get_flags(ref Value val);

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr g_strv_get_type();

		[DllImport(Global.GObjectNativeDll, CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr g_value_get_variant(ref Value val);
	}
}